//
// Created by hsj on 2022/1/12.
//
#include <iostream>
#include "t_class.h"


void my_class_hsj::Stock::acquire(const std::string & co,long n,double pr){
   company = co;
   if(n < 0){
     std::cout<<"number can not be less than 0, "<<company<<" while set to 0."<<std::endl;
     shares = 0;
   }
   else{
       shares = n;
   }
   share_val = pr;
   set_tot();
}

void my_class_hsj::Stock::buy(long num,double price){
   if(num < 0){
       std::cout<<"number of shares purchased can not be less than 0.transaction is aborted."<<std::endl;
   }
   else{
       shares += num;
       share_val = price;
       set_tot();
   }
}

void my_class_hsj::Stock::sell(long num,double price){
  using std::cout;
  using std::endl;

  if(num < 0){
      std::cout<<"number of shares purchased can not be less than 0. transaction is aborted."<<std::endl;
  }
  else if(num > shares){
      std::cout<<"you can not sell more than you have. transaction is aborted."<<std::endl;
  }
  else{
      shares -= num;
      share_val = price;
      set_tot();
  }
}


void my_class_hsj::Stock::update(double price){
  share_val = price;
  set_tot();
}


void my_class_hsj::Stock::show() const {//C++11,说明不会修改当前类实例对象
    //设置输出的格式
    std::ios_base::fmtflags original =  std::cout.setf(std::ios_base::fixed,std::ios_base::floatfield);//同步获取原始格式
    std::streamsize prec = std::cout.precision(2);//同步获取原始格式

    std::cout<<"*************************************************************"<<std::endl;
    std::cout<<"company: "<<company<<std::endl;
    std::cout<<"shares: "<<shares<<std::endl;
    std::cout<<"share price :$ "<<share_val<<std::endl;
    std::cout<<"total worth: "<<total_val<<std::endl;

    //恢复原始格式
    std::cout.setf(original,std::ios_base::floatfield);
    std::cout.precision(prec);
}
//this
//内部函数可以访问private成员
const my_class_hsj::Stock & my_class_hsj::Stock::topValue(const my_class_hsj::Stock &stock) const{
//    if (stock.total_val > this->total_val){
    if (stock.total_val > (*this).total_val){
        return stock;
    }
    else{
        return *this;
    }
}

//常量
void my_class_hsj::Stock::show_enum_const() const{
    using std::cout;
    using std::endl;

    cout<<"enum normal: "<<this->Months_Normal<<" enum normal cast: "<<this->int_value_from_enum<<endl;
    M m =  my_class_hsj::Stock::M::Months;
    cout<<"enum class: "<<static_cast<unsigned int>(m)<<" enum class cast: "<<this->int_value_from_enum_class<<endl;

    cout<<"static const :"<<this->My_Months<<endl;
}
//****************************************************
//构造器、析构函数
//****************************************************
my_class_hsj::Stock::Stock(){
//    std::cout<<"default constructor for Stock"<<std::endl;
    company = "no name";
    shares = 0;
    share_val = 0.0;
    total_val = 0.0;
}
my_class_hsj::Stock::Stock(const std::string &company_param,long shares_param,double share_val_param){
//    std::cout<<"params constructor for Stock"<<std::endl;
    company = company_param;
    if (shares_param < 0){
        std::cout<<"shares_param can not be less than 0, shares while set to 0."<<std::endl;
        shares = 0;
    }
    else{
        shares = shares_param;
    }
    share_val = share_val_param;
    set_tot();
}
my_class_hsj::Stock::~Stock(){
    std::cout<<"~Stock finally running..."<<std::endl;
}

my_class_hsj::StockSub::StockSub(){
//    std::cout<<"default constructor for StockSub"<<std::endl;
    Stock();
}
my_class_hsj::StockSub::StockSub(const std::string &company_param,long shares_param,double share_val_param){
//    std::cout<<"params constructor for StockSub"<<std::endl;
    Stock(company_param,shares_param,share_val_param);
}
my_class_hsj::StockSub::~StockSub(){
    std::cout<<"~StockSub finally running..."<<std::endl;
}


//        多态测试
//        static_cast	用于良性转换，一般不会导致意外发生，风险很低。
//        const_cast	用于 const 与非 const、volatile 与非 volatile 之间的转换。
//        reinterpret_cast	高度危险的转换，这种转换仅仅是对二进制位的重新解释，不会借助已有的转换规则对数据进行调整，但是可以实现最灵活的 C++ 类型转换。
//        dynamic_cast	借助 RTTI（ Run-Time Type Identification），用于类型安全的向下转型（Downcasting）。
void my_class_hsj_other::TestPolymorphic::test_class_polymorphic_rf(my_class_hsj::Stock &stock){
    std::cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<std::endl;
    std::cout<<"my_class_hsj_other::TestPolymorphic::test_class_polymorphic_rf"<<std::endl;
    static_cast<my_class_hsj::StockSub&>(stock).s_end();
}
void my_class_hsj_other::TestPolymorphic::test_class_polymorphic_pointer(my_class_hsj::Stock *stock){
    std::cout<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<std::endl;
    std::cout<<"my_class_hsj_other::TestPolymorphic::test_class_polymorphic_pointer"<<std::endl;
    static_cast<my_class_hsj::StockSub*>(stock)->s_end();
    (*static_cast<my_class_hsj::StockSub*>(stock)).s_end();
}